﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TaskRepository.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   Repository class that encapsulates all access to a SharePoint task list.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Collaboris.DataAccess.Test.Repositories
{
    using System;

    using Collaboris.DataAccess.SharePoint;
    using Collaboris.DataAccess.Test.Data_Entities;

    using Microsoft.SharePoint;

    /// <summary>
    /// Repository class that encapsulates all access to a SharePoint task list.
    /// </summary>
    public class TaskRepository : SPListRepository<TaskInfo>
    {
        #region Constants and Fields

        /// <summary>
        /// The priority converter.
        /// </summary>
        private GenericConverter<Priority, string> priorityConverter = new GenericConverter<Priority, string>();

        /// <summary>
        /// The status converter.
        /// </summary>
        private GenericConverter<Status, string> statusConverter = new GenericConverter<Status, string>();

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="TaskRepository"/> class. 
        /// The name of the list encapsulated by this repository
        /// </summary>
        /// <summary>
        /// Initializes a new instance of the <see cref="TaskRepository"/> class. 
        /// Creates a Repository class to access the given list in the given web.
        /// </summary>
        /// <param name="web">
        /// Instance of the SPWeb containing the list
        /// </param>
        /// <param name="listName">
        /// The list Name.
        /// </param>
        public TaskRepository(SPWeb web, string listName)
            : base(web, listName)
        {
            this.InitialiseStatusConverter();
            this.InitialisePriorityConverter();
        }

        /// <summary>
        /// The priority converter.
        /// </summary>
        public GenericConverter<Priority, string> PriorityConverter
        {
            get
            {
                return this.priorityConverter;
            }
        }

        /// <summary>
        /// The status converter.
        /// </summary>
        public GenericConverter<Status, string> StatusConverter
        {
            get
            {
                return this.statusConverter;
            }
        }

        #endregion

        #region Helper Methods

        /// <summary>
        /// Converts a SP list item into a business object
        /// </summary>
        /// <param name="srcListItem">
        /// The src List Item.
        /// </param>
        /// <param name="dstBusinessObject">
        /// The dst Business Object.
        /// </param>
        protected override void DataMap(SPListItem srcListItem, ref TaskInfo dstBusinessObject)
        {
            // Gets the title 
            // Demonstrates how to get a simple string value
            if (srcListItem.Fields.ContainsField(FieldNames.Title))
            {
                dstBusinessObject.Title = SPListHelper.GetColumnStringValue(srcListItem, FieldNames.Title);
            }

            // Demonstrates how to get the login name and the email of the user assigned to the task
            if (srcListItem.Fields.ContainsField(FieldNames.TaskOwner))
            {
                string assignedTo = SPListHelper.GetColumnStringValue(srcListItem, FieldNames.TaskOwner);
                if (!String.IsNullOrEmpty(assignedTo))
                {
                    var userLookup = new SPFieldUserValue(this.Web, assignedTo);
                    if (userLookup.User != null)
                    {
                        dstBusinessObject.TaskOwner.UserName = userLookup.User.LoginName;
                        dstBusinessObject.TaskOwner.Email = userLookup.User.Email;
                        dstBusinessObject.TaskOwner.UserId = userLookup.User.ID;
                    }
                }
            }

            // Gets the due date
            if (srcListItem.Fields.ContainsField(FieldNames.DueDate))
            {
                dstBusinessObject.DueDate = (DateTime)SPListHelper.GetColumnValue(srcListItem, FieldNames.DueDate);
            }

            // Gets the priority
            if (srcListItem.Fields.ContainsField(FieldNames.Priority))
            {
                dstBusinessObject.Priority =
                    this.PriorityConverter.Convert(SPListHelper.GetColumnStringValue(srcListItem, FieldNames.Priority));
            }

            // Gets the Status
            if (srcListItem.Fields.ContainsField(FieldNames.Status))
            {
                dstBusinessObject.Status =
                    this.StatusConverter.Convert(SPListHelper.GetColumnStringValue(srcListItem, FieldNames.Status));
            }
        }

        /// <summary>
        /// Converts business object into an SPListItem
        /// </summary>
        /// <param name="srcBusinessObject">
        /// The src Business Object.
        /// </param>
        /// <param name="dstListItem">
        /// The dst List Item.
        /// </param>
        protected override void DataMap(TaskInfo srcBusinessObject, ref SPListItem dstListItem)
        {
            // Sets the value for title column
            SPListHelper.SetColumnValue(dstListItem, FieldNames.Title, srcBusinessObject.Title);

            // Set the value of the task owner
            // Demonstrates how to set the value of a lookup user field if we only know the username
            SPUser user = SPHelpers.EnsureUser(this.Web, srcBusinessObject.TaskOwner.UserName);
            if (user != null)
            {
                SPListHelper.SetColumnValue(
                    dstListItem, FieldNames.TaskOwner, new SPFieldUserValue(this.Web, user.ID, user.LoginName));
            }

            // Sets the priority value
            SPListHelper.SetColumnValue(
                dstListItem, FieldNames.Priority, this.PriorityConverter.Convert(srcBusinessObject.Priority));

            // Sets the due date
            SPListHelper.SetColumnValue(dstListItem, FieldNames.DueDate, srcBusinessObject.DueDate);

            // Sets the priority
            SPListHelper.SetColumnValue(
                dstListItem, FieldNames.Status, this.StatusConverter.Convert(srcBusinessObject.Status));
        }

        /// <summary>
        /// Specifies the columns to be used by the query
        /// </summary>
        /// <param name="columns">
        /// </param>
        protected override void SetListColumns(QueryColumnCollection columns)
        {
            columns.Add(FieldNames.Title);
            columns.Add(FieldNames.TaskOwner);
            columns.Add(FieldNames.DueDate);
            columns.Add(FieldNames.Priority);
            columns.Add(FieldNames.Status);
        }

        /// <summary>
        /// The initialise priority converter.
        /// </summary>
        private void InitialisePriorityConverter()
        {
            this.PriorityConverter.Add(Priority.High, "(1) High");
            this.PriorityConverter.Add(Priority.Normal, "(2) Normal");
            this.PriorityConverter.Add(Priority.Low, "(3) Low");
        }

        /// <summary>
        /// The initialise status converter.
        /// </summary>
        private void InitialiseStatusConverter()
        {
            this.StatusConverter.Add(Status.NotStarted, "Not Started");
            this.StatusConverter.Add(Status.Completed, "Completed");
            this.StatusConverter.Add(Status.Deferred, "Deferred");
            this.StatusConverter.Add(Status.InProgress, "In Progress");
            this.StatusConverter.Add(Status.Waiting, "Waiting");
        }

        #endregion

        /// <summary>
        /// Names of the list item coolumns used by this repository
        /// </summary>
        public struct FieldNames
        {
            #region Constants and Fields

            /// <summary>
            /// The due date.
            /// </summary>
            public const string DueDate = "DueDate";

            /// <summary>
            /// The priority.
            /// </summary>
            public const string Priority = "Priority";

            /// <summary>
            /// The status.
            /// </summary>
            public const string Status = "Status";

            /// <summary>
            /// The task owner.
            /// </summary>
            public const string TaskOwner = "AssignedTo";

            /// <summary>
            /// The title.
            /// </summary>
            public const string Title = "Title";

            #endregion
        }
    }
}